package chair;

/**
 * Un contexte est représenté sous la forme d'un tableau et d'une récompense
 * associée. Chaque valeur du tableau représente l'information provenant d'un
 * organe. -1 signifie qu'elle n'est pas pertinente en tant que contexte (une
 * information transmise a déjà duré moins de Chronos.CONTEXT_WINDOW_TIME) sinon
 * la valeur représente cette information.
 * 
 * @author nomhad
 * 
 */
final class Context {
	/**
	 * L'activité et la pertinence de chaque organe est représenté sous forme
	 * d'un byte.
	 */
	private byte[] _vector;
	/** Mémorise la récompense/puntion que le robot a reçu pendant ce contexte */
	private int _reward;

	/**
	 * Quel est la récompense associée à ce contexte ?
	 * 
	 * @return ladite valeur
	 */
	int getReward() {
		return _reward;
	}

	/**
	 * Utilisé par Hippocampus pour réinitialiser récompense associée au
	 * contexte une fois qu'on a récupéré la récompense passée.
	 * 
	 * @param reward
	 *            nouvelles récompense à associer au contexte
	 */
	void setReward(int reward) {
		_reward = reward;
	}

	/**
	 * Brain signale à Hippocampus un stimulus, celui-ci met à jour la
	 * récompense du contexte courant
	 * 
	 * @param value
	 *            la récompense doit s'incrémenter de cette valeur
	 */
	void addToReward(int value) {
		_reward += value;
	}

	/**
	 * Context ne duplique pas le tableau
	 * 
	 * @param vector
	 *            tableau représentant le contexte
	 */
	Context(byte[] vector) {
		_vector = vector;
		_reward = 0;
	}

	@Override
	public int hashCode() {
		// Pas de Arrays.hashCode() : à la main.
		int hash = 3;
		for (int i = 0; i < _vector.length; i++)
			hash = 7 * hash + _vector[i];
		return hash;
	}

	/**
	 * Dans le cas ou l'information envoyée par un organe n'est plus
	 * significative (-1) il est nécessaire à Hippocampus de récupérer les
	 * anciens contextes lui ressemblant, alors qu'il fournissait une valeur.
	 * 
	 * Par rapport à equals() c'est donc plutôt une non différence qu'on calcule
	 * ici.
	 * 
	 * Un vecteur [0, 1, 1] sera égal à [-1, 1, 1] mais différent de [1, 1, 1].
	 */
	boolean seems(Object obj) {
		// Deux contextes se ressemblent si les valeurs significatives de leurs
		// vecteurs son identiques.
		if (obj instanceof Context) {
			Context other = (Context) obj;
			if (other._vector.length != _vector.length)
				return false;
			for (int i = 0; i < _vector.length; i++)
				if (_vector[i] != other._vector[i] && _vector[i] != -1
						&& other._vector[i] != -1)
					return false;
			return true;
		}
		return false;
	}

	@Override
	public boolean equals(Object obj) {
		// Deux contextes sont égaux si leurs vecteurs sont identiques.
		if (obj instanceof Context) {
			Context other = (Context) obj;
			if (other._vector.length != _vector.length)
				return false;
			for (int i = 0; i < _vector.length; i++)
				if (_vector[i] != other._vector[i])
					return false;
			return true;
		}
		return false;
	}

	@Override
	public String toString() {
		String str = "[";
		for (int i = 0; i < _vector.length; i++)
			str += _vector[i] + ",";
		str += "]";
		return str;
	}
}